package com.ligq.vbasedemo.encode

import android.hardware.display.DisplayManager
import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.media.projection.MediaProjection
import android.util.Log
import com.ligq.common.utils.FileUtils
import com.ligq.vbasedemo.MainActivity.TAG

/**
 * 屏幕录制编码器
 */
class H264SREncode(mediaProjection: MediaProjection) : Thread() {
    private lateinit var mediaCodec: MediaCodec
    private val width = 640
    private val height = 1920

    init {
        val mediaFormat =
            MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height)
        try {
            mediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC)
            //帧率--20帧/s
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 20)
            //I帧间隔--30帧一个I帧
            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 30)
            //码率越高，质量越清晰
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, width * height)
            //设置数据来源，是从surface来的
            mediaFormat.setInteger(
                MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
            )
            //配置编码标志位
            mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
            //提供场地
            val createInputSurface = mediaCodec.createInputSurface()
            //录屏的数据显示到屏幕-->虚拟屏幕
            mediaProjection.createVirtualDisplay(
                "screen_recording",
                width,
                height,
                3,//1dp=3px
                DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,//公开
                createInputSurface,
                null,//录屏开始，结束，暂停回调
                null//接收一些消息，并携带数据
            )
        } catch (e: Exception) {
            Log.e(TAG, ": ", e)
        }
    }


    override fun run() {
        super.run()
        mediaCodec.start()
        val bufferInfo = MediaCodec.BufferInfo()
        //录屏数据直接由MediaProjection传输给dsp，由dsp直接编码
        while (true) {
            val outIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000)
            if (outIndex >= 0) {
                val outputBuffer = mediaCodec.getOutputBuffer(outIndex)
                val data = ByteArray(outputBuffer!!.remaining())
                outputBuffer.get(data)//将outputBuffer的数据转移到data字节数组中
                FileUtils.writeBytes(data)
                FileUtils.writeContent(data)
                mediaCodec.releaseOutputBuffer(outIndex, false)
            }
        }
    }
}